import {
  HttpException,
  HttpStatus,
  Injectable,
  NestMiddleware,
} from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
import { ConfigService } from 'src/cus-modules/config/config.service';
import getWXOfficeAccessToken from 'src/utils/getWXOfficeAccessToken';

@Injectable()
export class AttachAccessToken implements NestMiddleware {
  private accessToken: string;
  private expiresIn: number;

  constructor(private readonly configService: ConfigService) {}

  async use(req: any, res: Response, next: NextFunction) {
    const requestObj: Request = req as Request;
    console.log('request...', requestObj.originalUrl);
    if (
      !this.expiresIn ||
      !this.accessToken ||
      (this.expiresIn && Date.now() - this.expiresIn >= 7200)
    ) {
      try {
        const { access_token, expires_in } = await getWXOfficeAccessToken(
          this.configService.get('APP_ID'),
          this.configService.get('APP_SECRET'),
        );
        this.accessToken = access_token;
        this.expiresIn = Date.now() + expires_in - 20;
      } catch (error) {
        if (error?.errmsg !== 'ok') {
          throw new HttpException(
            `wx_access_token_error ${error.errcode}: ${error.errmsg}`,
            HttpStatus.UNAUTHORIZED,
          );
        } else {
          throw new HttpException(
            `wx_access_token_error fetch: ${
              error?.message || JSON.stringify(error.stack, null, ' ')
            }`,
            HttpStatus.UNAUTHORIZED,
          );
        }
      }
    }
    if (!this.accessToken) {
      throw new HttpException('wx_access_token_error', HttpStatus.UNAUTHORIZED);
    }

    req.accessToken = this.accessToken;
    req.expiresIn = this.expiresIn;
    next();
  }
}
